package com.jcli.fx3u;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.net.Socket;

public class FX3UDataReaderGUI extends JFrame {
    private JTextArea textArea;
    private JButton connectButton;
    private JButton readButton;
    private Socket socket;
    private DataInputStream dataInputStream;
    private DataOutputStream dataOutputStream;

    public FX3UDataReaderGUI() {
        setTitle("FX3U Data Reader");
        setSize(400, 300);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        JPanel panel = new JPanel(new BorderLayout());

        textArea = new JTextArea();
        JScrollPane scrollPane = new JScrollPane(textArea);
        panel.add(scrollPane, BorderLayout.CENTER);

        JPanel buttonPanel = new JPanel();
        connectButton = new JButton("Connect");
        readButton = new JButton("Read D Registers");
        readButton.setEnabled(false); // 初始状态下读取按钮禁用
        buttonPanel.add(connectButton);
        buttonPanel.add(readButton);
        panel.add(buttonPanel, BorderLayout.SOUTH);

        add(panel);

        connectButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if (socket == null || socket.isClosed()) {
                    connectToPLC();
                }
            }
        });

        readButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if (socket != null && socket.isConnected()) {
                    readDRegisters();
                }
            }
        });
    }

    private void connectToPLC() {
        try {
            // 连接到FX3U PLC的Modbus TCP端口（默认是502）
            socket = new Socket("192.168.1.11", 3000);
            dataInputStream = new DataInputStream(socket.getInputStream());
            dataOutputStream = new DataOutputStream(socket.getOutputStream());

            // 显示连接成功消息
            JOptionPane.showMessageDialog(this, "Connected to PLC.", "Info", JOptionPane.INFORMATION_MESSAGE);
            readButton.setEnabled(true); // 连接成功后启用读取按钮
        } catch (Exception ex) {
            JOptionPane.showMessageDialog(this, "Connection failed: " + ex.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
        }
    }

    private void readDRegisters() {
        try {
            // D寄存器的起始地址（示例为D100）
            String startAddress = "D100";

            // 读取的寄存器数量
            int registerCount = 10;

            // 构造Modbus TCP请求帧
            byte[] modbusRequest = buildReadRequest((short) 1, startAddress, (short) registerCount);

            // 发送请求
            dataOutputStream.write(modbusRequest);

            // 接收响应
            byte[] modbusResponse = new byte[256];
            int bytesRead = dataInputStream.read(modbusResponse);

            // 解析响应
            String result = parseReadResponse(modbusResponse, bytesRead);

            // 在文本区域中显示结果
            textArea.append(result + "\n");
        } catch (Exception ex) {
            JOptionPane.showMessageDialog(this, "Failed to read from PLC: " + ex.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
        }
    }

    private byte[] buildReadRequest(short unitId, String startAddress, short registerCount) {
        // Modbus TCP Header
        byte[] request = new byte[12];
        request[0] = 0x00;
        request[1] = 0x01;
        request[2] = 0x00;
        request[3] = 0x00;
        request[4] = 0x00;
        request[5] = 0x06;
        request[6] = (byte) unitId;
        request[7] = 0x03; // Read Holding Registers
        request[8] = (byte) (Integer.parseInt(startAddress.substring(1)) >> 8); // 高位
        request[9] = (byte) (Integer.parseInt(startAddress.substring(1)) & 0xFF); // 低位
        request[10] = 0x00; // 高位
        request[11] = (byte) registerCount; // 低位

        return request;
    }

    private String parseReadResponse(byte[] response, int bytesRead) {
        // Modbus TCP response starts from byte 9
        int byteCount = response[8];
        StringBuilder result = new StringBuilder();

        for (int i = 0; i < byteCount / 2; i++) {
            // Combine two bytes into a 16-bit integer
            short value = (short) ((response[9 + i * 2] << 8) | (response[10 + i * 2] & 0xFF));

            // Append the value to the result
            result.append(value).append(" ");
        }

        return result.toString().trim();
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                FX3UDataReaderGUI gui = new FX3UDataReaderGUI();
                gui.setVisible(true);
            }
        });
    }
}
